會想整理這篇筆記是因為在這篇官方文件的 Challenge 1 的程式碼遇到自己和同學當下都難以解釋的現象
(以下會簡單解釋,但先觀看上方 challenge 內容再看會比較好理解):
已知觸發 Last name <input />
會讓 player 物件只留下 lastName 的屬性,所以其他因 player 所生的畫面會消失,像是 score <label>
確實地消失了,但... First name <input />
你怎麼還在???這時留意到 console 跳出了關鍵的提示 Warning: A component is changing a controlled input to be uncontrolled
於是就開始挖坑了...
<input />
所做的事當只有放 <input />
,使用者輸入文字瀏覽器會
當我們在 <input />
裡面擺入 value 屬性,input 裡會出現 value 設定的值,且因為是寫死的值,所以無法改動
<input />
?<input />
(留意圖中紫色的字為瀏覽器本身就會做的事value={text}
置入的,和當初使用者輸入進去的有差比較一下 React 介入前後的程式碼,會思考同樣的畫面呈現,何必要寫成 React 這樣這麼多的程式碼?
當然是有好處的!
Before: document.querySelector('.user-input').value
After: text
Before: document.querySelector('.user-input').value = '更新的值'
After: setText('更新的值')
如此一來可以設計許多進階的功能,比如我們如果希望使用者在輸入的同時,畫面某處也會即時顯示他的輸入內容,就能輕易做到!不用再手動取值,然後更改 DOM 諸如此類...
在理解瀏覽器本身就會對 <input />
做些處理,以及也能設計 React 去擁有控制權之後,接著來看React 官方文件 - input,可以知道 <input>
這個元件本身是 uncontrolled 的,但可以透過設定 value、checked 屬性(後者是 for checkbox input or radio button),來讓它變成 controlled 的狀態。而在設定成 controlled 的狀態後,就必須設定 onChange handler 來更新 value(不然 value 會固定住)
.
接著官方文件提到了很多點注意事項,為了專注於 Warning,這裡只點出三點:
undefined
或 null
,若希望初始值是空的,就擺入空字串''
,不然還是會被視為 uncontrolled.
有了以上背景知識就可以來討論遇到的 Warning 了!
在 challenge 的情境,原本 player.firstName 是有值的,一旦觸發 Last name <input />
讓 player 物件只留下 lastName 的屬性,所以 First name <input />
的 value={player.firstName} 變為 undefined,這讓First name <input />
瞬間變成 uncontrolled 的元件,於是就噴了 Warning。這時 First name <input />
是在 uncontrolled 的狀態下保持了原本輸入在 input 框框中的內容,也就是為何裡面的值還在的原因
.
在「筆記一」的情境,是由於原本 <input />
沒有寫 value 屬性來控制,加入value="你改不了我~~"
的瞬間,就如同文件所說,變成 controlled 元件,會噴 Warning 是因為違反了上面第二點注意事項,它在這個 lifttime 從 uncontrolled 變 controlled
.
同場加映(?)
測試注意事項第三點,設定 useState(undefined)
,在使用者輸入值觸發一切連環效應後...
Modern React with Redux [2023 Update] - Handling Input Element
以上,有任何想法或文內有誤、不清楚歡迎提出,謝謝大家 🙏🏻
.
Special thanks to 一起討論的同學和助教!